package com.tiennt.android.chinesechess.models.quanco;

import java.util.ArrayList;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;

import com.tiennt.android.chinesechess.models.BanCo;
import com.tiennt.android.chinesechess.models.Coord;

public abstract class QuanCo {
	public static final int cPHE_DO = 1;
	public static final int cPHE_DEN = 2;
	public static final int cTRANGTHAI_NORMAL = 1;
	public static final int cTRANGTHAI_MARKED = 2;
	public static final int cTRANGTHAI_BIAN = 3;
	public static final int cTRANGTHAI_UP = 4;
	public static final int cTRANGTHAI_UP_MARKED = 5;
	public static final int cTRANGTHAI_BICHIEU = 6;

	public static final int cNOTVALIDMOVE_BICHIEU = 1;
	public static final int cNOTVALIDMOVE_CHONGTUONG = 2;
	public static final int cNOTVALIDMOVE_OTHERS = 3;
	public static final int cVALIDMOVE = 4;

	public static final String cQUANMA = "ma";
	public static final String cQUANPHAO = "phao";
	public static final String cQUANSY = "sy";
	public static final String cQUANTINH = "tinh";
	public static final String cQUANTOT = "tot";
	public static final String cQUANTUONG = "tuong";
	public static final String cQUANXE = "xe";

	// Debug purpose.
	private boolean DBG = true;
	private String TAG = "QuanCo";

	public int mHang;
	public int mCot;

	public String mTen;

	public String mTenThat;

	public int mPhe;

	public int mThuTu;

	public int mTrangThai;

	public boolean mKhoa = false;

	public BanCo mBanCo;

	public abstract void drawItself(Canvas canvas, Paint paint, BanCo banCo);

	public void toggleTrangThai() {
		if (mTrangThai == cTRANGTHAI_NORMAL) {
			mTrangThai = cTRANGTHAI_MARKED;
		} else if (mTrangThai == cTRANGTHAI_MARKED) {
			mTrangThai = cTRANGTHAI_NORMAL;
		} else if (mTrangThai == cTRANGTHAI_UP) {
			mTrangThai = cTRANGTHAI_UP_MARKED;
		} else if (mTrangThai == cTRANGTHAI_UP_MARKED) {
			mTrangThai = cTRANGTHAI_UP;
		}
	}

	public ArrayList<Coord> calculatePosibleMoves(BanCo banCo) {
		ArrayList<Coord> hints = new ArrayList<Coord>();

		if (mTen.equals(QuanCo.cQUANTOT)) {
			if (mPhe == QuanCo.cPHE_DO) {
				if (mHang < 5) {
					if (!(banCo.mOCo[mHang + 1][mCot].mQuanCo != null && banCo.mOCo[mHang + 1][mCot].mQuanCo.mPhe == mPhe)) {
						hints.add(new Coord(mHang + 1, mCot));
					}

				} else {
					if (mHang + 1 < 10) {
						if (!(banCo.mOCo[mHang + 1][mCot].mQuanCo != null && banCo.mOCo[mHang + 1][mCot].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang + 1, mCot));
						}
					}

					if (mCot + 1 < 9) {
						if (!(banCo.mOCo[mHang][mCot + 1].mQuanCo != null && banCo.mOCo[mHang][mCot + 1].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang, mCot + 1));
						}
					}

					if (mCot - 1 > -1) {
						if (!(banCo.mOCo[mHang][mCot - 1].mQuanCo != null && banCo.mOCo[mHang][mCot - 1].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang, mCot - 1));
						}
					}
				}
			} else {
				if (mHang >= 5) {
					if (!(banCo.mOCo[mHang - 1][mCot].mQuanCo != null && banCo.mOCo[mHang - 1][mCot].mQuanCo.mPhe == mPhe)) {
						hints.add(new Coord(mHang - 1, mCot));
					}
				} else {
					if (mHang - 1 > -1) {
						if (!(banCo.mOCo[mHang - 1][mCot].mQuanCo != null && banCo.mOCo[mHang - 1][mCot].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang - 1, mCot));
						}
					}

					if (mCot + 1 < 9) {
						if (!(banCo.mOCo[mHang][mCot + 1].mQuanCo != null && banCo.mOCo[mHang][mCot + 1].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang, mCot + 1));
						}
					}

					if (mCot - 1 > -1) {
						if (!(banCo.mOCo[mHang][mCot - 1].mQuanCo != null && banCo.mOCo[mHang][mCot - 1].mQuanCo.mPhe == mPhe)) {
							hints.add(new Coord(mHang, mCot - 1));
						}
					}
				}
			}
		} else if (mTen.equals(QuanCo.cQUANXE)) {
			int r = mHang;
			int c = mCot;

			r--;
			while (r >= 0) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (banCo.mOCo[r][c].mQuanCo.mPhe == mPhe) {
						break;
					} else {
						hints.add(new Coord(r, c));
						break;
					}
				}
				hints.add(new Coord(r, c));
				r--;
			}

			r = mHang;
			r++;
			while (r <= 9) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (banCo.mOCo[r][c].mQuanCo.mPhe == mPhe) {
						break;
					} else {
						hints.add(new Coord(r, c));
						break;
					}
				}
				hints.add(new Coord(r, c));
				r++;
			}

			r = mHang;
			c = mCot;

			c--;
			while (c >= 0) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (banCo.mOCo[r][c].mQuanCo.mPhe == mPhe) {
						break;
					} else {
						hints.add(new Coord(r, c));
						break;
					}
				}
				hints.add(new Coord(r, c));
				c--;
			}

			c = mCot;
			c++;
			while (c <= 8) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (banCo.mOCo[r][c].mQuanCo.mPhe == mPhe) {
						break;
					} else {
						hints.add(new Coord(r, c));
						break;
					}
				}
				hints.add(new Coord(r, c));
				c++;
			}

		} else if (mTen.equals(QuanCo.cQUANPHAO)) {
			int r = mHang;
			int c = mCot;

			r--;
			boolean lastChange = false;

			while (r >= 0) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (lastChange) {
						if (banCo.mOCo[r][c].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r, c));
						}
						break;
					} else {
						lastChange = true;
					}
				}
				if (!lastChange) {
					hints.add(new Coord(r, c));
				}
				r--;
			}

			r = mHang;
			r++;
			lastChange = false;

			while (r <= 9) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (lastChange) {
						if (banCo.mOCo[r][c].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r, c));
						}
						break;

					} else {
						lastChange = true;
					}
				}
				if (!lastChange) {
					hints.add(new Coord(r, c));
				}
				r++;
			}

			r = mHang;
			c = mCot;

			c--;
			lastChange = false;

			while (c >= 0) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (lastChange) {
						if (banCo.mOCo[r][c].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r, c));
						}
						break;

					} else {
						lastChange = true;
					}
				}
				if (!lastChange) {
					hints.add(new Coord(r, c));
				}
				c--;
			}

			c = mCot;
			c++;
			lastChange = false;

			while (c <= 8) {
				if (banCo.mOCo[r][c].mQuanCo != null) {
					if (lastChange) {
						if (banCo.mOCo[r][c].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r, c));
						}
						break;

					} else {
						lastChange = true;
					}
				}
				if (!lastChange) {
					hints.add(new Coord(r, c));
				}
				c++;
			}

		} else if (mTen.equals(QuanCo.cQUANSY)) {
			int r = mHang;
			int c = mCot;

			if (mTrangThai == cTRANGTHAI_UP_MARKED
					|| mTrangThai == cTRANGTHAI_UP) {
				if (mHang == 0 && (mCot == 3 || mCot == 5)) {
					if (banCo.mOCo[1][4].mQuanCo == null
							|| banCo.mOCo[1][4].mQuanCo.mPhe != mPhe){
						hints.add(new Coord(1, 4));
					}
					
				} else if (mHang == 9 && (mCot == 3 || mCot == 5)) {
					if (banCo.mOCo[8][4].mQuanCo == null
							|| banCo.mOCo[8][4].mQuanCo.mPhe != mPhe){
						hints.add(new Coord(8, 4));
					}
				}

			} else {
				if (r - 1 >= 0 && c - 1 >= 0) {
					if (banCo.mOCo[r - 1][c - 1].mQuanCo == null
							|| banCo.mOCo[r - 1][c - 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 1, c - 1));
					}
				}

				if (r - 1 >= 0 && c + 1 <= 8) {
					if (banCo.mOCo[r - 1][c + 1].mQuanCo == null
							|| banCo.mOCo[r - 1][c + 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 1, c + 1));
					}
				}

				if (r + 1 <= 9 && c - 1 >= 0) {
					if (banCo.mOCo[r + 1][c - 1].mQuanCo == null
							|| banCo.mOCo[r + 1][c - 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 1, c - 1));
					}
				}

				if (r + 1 <= 9 && c + 1 <= 8) {
					if (banCo.mOCo[r + 1][c + 1].mQuanCo == null
							|| banCo.mOCo[r + 1][c + 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 1, c + 1));
					}
				}
			}

		} else if (mTen.equals(QuanCo.cQUANTINH)) {
			int r = mHang;
			int c = mCot;

			if (r - 2 >= 0 && c - 2 >= 0) {
				if (banCo.mOCo[r - 1][c - 1].mQuanCo == null) {
					if (banCo.mOCo[r - 2][c - 2].mQuanCo == null
							|| banCo.mOCo[r - 2][c - 2].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 2, c - 2));
					}
				}
			}

			if (r - 2 >= 0 && c + 2 <= 8) {
				if (banCo.mOCo[r - 1][c + 1].mQuanCo == null) {
					if (banCo.mOCo[r - 2][c + 2].mQuanCo == null
							|| banCo.mOCo[r - 2][c + 2].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 2, c + 2));
					}
				}
			}

			if (r + 2 <= 9 && c - 2 >= 0) {
				if (banCo.mOCo[r + 1][c - 1].mQuanCo == null) {
					if (banCo.mOCo[r + 2][c - 2].mQuanCo == null
							|| banCo.mOCo[r + 2][c - 2].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 2, c - 2));
					}
				}
			}

			if (r + 2 <= 9 && c + 2 <= 8) {
				if (banCo.mOCo[r + 1][c + 1].mQuanCo == null) {
					if (banCo.mOCo[r + 2][c + 2].mQuanCo == null
							|| banCo.mOCo[r + 2][c + 2].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 2, c + 2));
					}
				}
			}

		} else if (mTen.equals(QuanCo.cQUANTUONG)) {
			int r = mHang;
			int c = mCot;

			if (mPhe == QuanCo.cPHE_DO) {
				if (r + 1 <= 2) {
					if (banCo.mOCo[r + 1][c].mQuanCo == null
							|| banCo.mOCo[r + 1][c].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 1, c));
					}
				}

				if (r - 1 >= 0) {
					if (banCo.mOCo[r - 1][c].mQuanCo == null
							|| banCo.mOCo[r - 1][c].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 1, c));
					}
				}

				if (c - 1 >= 3) {
					if (banCo.mOCo[r][c - 1].mQuanCo == null
							|| banCo.mOCo[r][c - 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r, c - 1));
					}
				}

				if (c + 1 <= 5) {
					if (banCo.mOCo[r][c + 1].mQuanCo == null
							|| banCo.mOCo[r][c + 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r, c + 1));
					}
				}
			} else {
				if (r + 1 <= 9) {
					if (banCo.mOCo[r + 1][c].mQuanCo == null
							|| banCo.mOCo[r + 1][c].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r + 1, c));
					}
				}

				if (r - 1 >= 7) {
					if (banCo.mOCo[r - 1][c].mQuanCo == null
							|| banCo.mOCo[r - 1][c].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r - 1, c));
					}
				}

				if (c - 1 >= 3) {
					if (banCo.mOCo[r][c - 1].mQuanCo == null
							|| banCo.mOCo[r][c - 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r, c - 1));
					}
				}

				if (c + 1 <= 5) {
					if (banCo.mOCo[r][c + 1].mQuanCo == null
							|| banCo.mOCo[r][c + 1].mQuanCo.mPhe != mPhe) {
						hints.add(new Coord(r, c + 1));
					}
				}
			}
		} else if (mTen.equals(QuanCo.cQUANMA)) {
			int r = mHang;
			int c = mCot;

			if (c - 2 >= 0) {
				if (banCo.mOCo[r][c - 1].mQuanCo == null) {
					if (r - 1 >= 0) {
						if (banCo.mOCo[r - 1][c - 2].mQuanCo == null
								|| banCo.mOCo[r - 1][c - 2].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r - 1, c - 2));
						}
					}
					if (r + 1 <= 9) {
						if (banCo.mOCo[r + 1][c - 2].mQuanCo == null
								|| banCo.mOCo[r + 1][c - 2].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r + 1, c - 2));
						}
					}
				}
			}

			if (c + 2 <= 8) {
				if (banCo.mOCo[r][c + 1].mQuanCo == null) {
					if (r - 1 >= 0) {
						if (banCo.mOCo[r - 1][c + 2].mQuanCo == null
								|| banCo.mOCo[r - 1][c + 2].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r - 1, c + 2));
						}
					}
					if (r + 1 <= 9) {
						if (banCo.mOCo[r + 1][c + 2].mQuanCo == null
								|| banCo.mOCo[r + 1][c + 2].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r + 1, c + 2));
						}
					}
				}
			}

			if (r - 2 >= 0) {
				if (banCo.mOCo[r - 1][c].mQuanCo == null) {
					if (c - 1 >= 0) {
						if (banCo.mOCo[r - 2][c - 1].mQuanCo == null
								|| banCo.mOCo[r - 2][c - 1].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r - 2, c - 1));
						}
					}
					if (c + 1 <= 8) {
						if (banCo.mOCo[r - 2][c + 1].mQuanCo == null
								|| banCo.mOCo[r - 2][c + 1].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r - 2, c + 1));
						}
					}
				}
			}

			if (r + 2 <= 9) {
				if (banCo.mOCo[r + 1][c].mQuanCo == null) {
					if (c - 1 >= 0) {
						if (banCo.mOCo[r + 2][c - 1].mQuanCo == null
								|| banCo.mOCo[r + 2][c - 1].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r + 2, c - 1));
						}
					}
					if (c + 1 <= 8) {
						if (banCo.mOCo[r + 2][c + 1].mQuanCo == null
								|| banCo.mOCo[r + 2][c + 1].mQuanCo.mPhe != mPhe) {
							hints.add(new Coord(r + 2, c + 1));
						}
					}
				}
			}
		}

		return hints;
	}

	public boolean isDead() {
		return mTrangThai == cTRANGTHAI_BIAN ? true : false;
	}

	public void moveTo(int hang, int cot) {

		mBanCo.mOCo[mHang][mCot].mQuanCo = null;
		if (mBanCo.mOCo[hang][cot].mQuanCo != null) {
			mBanCo.mOCo[hang][cot].mQuanCo.mTrangThai = cTRANGTHAI_BIAN;
		}

		mBanCo.mOCo[hang][cot].mQuanCo = this;
		mHang = hang;
		mCot = cot;

		if (mTrangThai == cTRANGTHAI_MARKED) {
			mTrangThai = cTRANGTHAI_NORMAL;
		} else if (mTrangThai == cTRANGTHAI_UP_MARKED) {
			mTrangThai = cTRANGTHAI_NORMAL;
			mTen = mTenThat;
		}
	};

	public int isValidMove(int hang, int cot) {
		// Valid nghĩa là đi tới (hàng, cột) vừa phải đúng theo luật đi, vừa
		// phải không bị chiếu tướng.
		// log(mPossibleMoves.contains(new Coord(hang, cot)) + "");
		// log(isTuongAnToan(hang, cot) + "");

		if (calculatePosibleMoves(mBanCo).contains(new Coord(hang, cot))) {
			return isTuongAnToan(hang, cot);
		} else {
			return cNOTVALIDMOVE_OTHERS;
		}

//		return (calculatePosibleMoves(mBanCo).contains(new Coord(hang, cot)) && isTuongAnToan(
//				hang, cot));
	}

	public int isTuongAnToan(int hang, int cot) {
		// Input: Vị trí (i, j) phải trống hoặc là quân đối thủ.

		//
		int hangBak = mHang;
		int cotBak = mCot;

		QuanCo quanCoBak = mBanCo.mOCo[hang][cot].mQuanCo;
		// Chuyen quan minh di khoi vi tri hien tai.
		mBanCo.mOCo[mHang][mCot].mQuanCo = null;

		if (quanCoBak != null) {
			// Neu tai do co quan cua enemy thi an quan do
			mBanCo.mOCo[hang][cot].mQuanCo.mTrangThai = cTRANGTHAI_BIAN;

		}

		// Sau do di quan co cua minh toi cho do.
		mBanCo.mOCo[hang][cot].mQuanCo = this;

		// Update thong tin quan co
		mHang = hang;
		mCot = cot;

		int result = 0;
		if (mBanCo.isBiChieu(mPhe)) {
			result = cNOTVALIDMOVE_BICHIEU;
		} else if (mBanCo.isChongTuong()) {
			result = cNOTVALIDMOVE_CHONGTUONG;
		} else {
			result = cVALIDMOVE;
		}

		// boolean result2 = !mBanCo.isBiChieu(mPhe) && !mBanCo.isChongTuong();

		mBanCo.mOCo[hang][cot].mQuanCo = quanCoBak;
		mHang = hangBak;
		mCot = cotBak;
		mBanCo.mOCo[mHang][mCot].mQuanCo = this;

		log("RESULT: " + result + "");
		return result;
	}

	public void log(final String message) {
		if (DBG) {
			Log.d(TAG, message);
		}
	}
}
